/*
 * SturaMainFrame.java
 *
 * Copyright (C) 2014 Fabian Wenzelmann
 *
 * This file is part of stura_voting.
 *
 * stura_voting is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * stura_voting is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with stura_voting.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

// mostly this code was crated by netbeans, so don't wonder if it's hard to read ;)

package de.stura;

import java.io.*;
import java.util.ArrayList;
import java.util.Vector;
import java.util.HashMap;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.ImageIcon;

import de.stura.median.*;
import de.stura.schulze.*;

/**
 * A swing frame for using the different voting procedures.
 */
public class SturaMainFrame extends javax.swing.JFrame {

    /**
     * Creates new form SturaMainFrame
     */
    public SturaMainFrame() {
        initComponents();
        initSelf();
    }
    
    private void initSelf() {
        this.fileChooser = new javax.swing.JFileChooser(".");
        javax.swing.filechooser.FileNameExtensionFilter filter = 
            new javax.swing.filechooser.FileNameExtensionFilter("txt Dateien", "txt");
        fileChooser.addChoosableFileFilter(filter);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        schulzePannel = new javax.swing.JTabbedPane();
        votersPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        votersTable = new javax.swing.JTable();
        addVoterRow = new javax.swing.JButton();
        ignoreWeightCheckBox = new javax.swing.JCheckBox();
        medianPanel = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        medianTable = new javax.swing.JTable();
        createMedianButton = new javax.swing.JButton();
        evaluateMedianButton = new javax.swing.JButton();
        medianAbsoluteMajorityCheckBox = new javax.swing.JCheckBox();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        schulzeTable = new javax.swing.JTable();
        createSchulzeButton = new javax.swing.JButton();
        evaluateSchulzeButton = new javax.swing.JButton();
        schulzeAbsoluteMajorityCheckBox = new javax.swing.JCheckBox();
        schulzeTwoThirdsMajorityCheckBox = new javax.swing.JCheckBox();
        evaluateMultipleSchulzeButton = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        openWeightMenuItem = new javax.swing.JMenuItem();
        saveWeightMenuItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        exitMenuItem = new javax.swing.JMenuItem();
        Help = new javax.swing.JMenu();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("StuRa Abstimmungen");

        votersTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Stimmgewicht"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Integer.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        jScrollPane1.setViewportView(votersTable);

        addVoterRow.setText("Zeile hinzufügen");
        addVoterRow.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addVoterRowActionPerformed(evt);
            }
        });

        ignoreWeightCheckBox.setText("Gewicht auf 1");

        javax.swing.GroupLayout votersPanelLayout = new javax.swing.GroupLayout(votersPanel);
        votersPanel.setLayout(votersPanelLayout);
        votersPanelLayout.setHorizontalGroup(
            votersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(votersPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 347, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(votersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(addVoterRow, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(ignoreWeightCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        votersPanelLayout.setVerticalGroup(
            votersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(votersPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(votersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE)
                    .addGroup(votersPanelLayout.createSequentialGroup()
                        .addComponent(addVoterRow)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(ignoreWeightCheckBox)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );

        schulzePannel.addTab("Wahlverzeichnis", votersPanel);

        medianTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Gewicht", "Betrag"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Integer.class, java.lang.Float.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, true
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane2.setViewportView(medianTable);

        createMedianButton.setText("Erstellen");
        createMedianButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createMedianButtonActionPerformed(evt);
            }
        });

        evaluateMedianButton.setText("Auswerten");
        evaluateMedianButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                evaluateMedianButtonActionPerformed(evt);
            }
        });

        medianAbsoluteMajorityCheckBox.setText("Absolute Mehrheit");

        javax.swing.GroupLayout medianPanelLayout = new javax.swing.GroupLayout(medianPanel);
        medianPanel.setLayout(medianPanelLayout);
        medianPanelLayout.setHorizontalGroup(
            medianPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(medianPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 353, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(medianPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(evaluateMedianButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(createMedianButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(medianAbsoluteMajorityCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        medianPanelLayout.setVerticalGroup(
            medianPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(medianPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(medianPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE)
                    .addGroup(medianPanelLayout.createSequentialGroup()
                        .addComponent(createMedianButton)
                        .addGap(18, 18, 18)
                        .addComponent(evaluateMedianButton)
                        .addGap(18, 18, 18)
                        .addComponent(medianAbsoluteMajorityCheckBox)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );

        schulzePannel.addTab("Median", medianPanel);

        schulzeTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Gewicht", "Reihung"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Integer.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, true
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane3.setViewportView(schulzeTable);

        createSchulzeButton.setText("Erstellen");
        createSchulzeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createSchulzeButtonActionPerformed(evt);
            }
        });

        evaluateSchulzeButton.setText("Auswerten");
        evaluateSchulzeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                evaluateSchulzeButtonActionPerformed(evt);
            }
        });

        schulzeAbsoluteMajorityCheckBox.setText("Absolute Mehrheit");

        schulzeTwoThirdsMajorityCheckBox.setText("<html><sup>2</sup>&frasl;<sub>3</sub> Mehrheit</html>");

        evaluateMultipleSchulzeButton.setText("Datei...");
        evaluateMultipleSchulzeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                evaluateMultipleSchulzeButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 353, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(createSchulzeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(evaluateSchulzeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(schulzeTwoThirdsMajorityCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 156, Short.MAX_VALUE)
                            .addComponent(evaluateMultipleSchulzeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(schulzeAbsoluteMajorityCheckBox)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(createSchulzeButton)
                        .addGap(18, 18, 18)
                        .addComponent(evaluateSchulzeButton)
                        .addGap(18, 18, 18)
                        .addComponent(evaluateMultipleSchulzeButton)
                        .addGap(18, 18, 18)
                        .addComponent(schulzeAbsoluteMajorityCheckBox)
                        .addGap(9, 9, 9)
                        .addComponent(schulzeTwoThirdsMajorityCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE))
                .addContainerGap())
        );

        schulzePannel.addTab("Schulze", jPanel1);

        fileMenu.setText("Datei");

        openWeightMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        openWeightMenuItem.setText("Wahlgewichtung öffnen");
        openWeightMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openWeightMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(openWeightMenuItem);

        saveWeightMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        saveWeightMenuItem.setText("Wahlgewichtung speichern");
        saveWeightMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveWeightMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveWeightMenuItem);
        fileMenu.add(jSeparator1);

        exitMenuItem.setText("Beenden");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        jMenuBar1.add(fileMenu);

        Help.setText("Hilfe");
        Help.add(jSeparator2);

        aboutMenuItem.setText("About");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        Help.add(aboutMenuItem);

        jMenuBar1.add(Help);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(schulzePannel)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(schulzePannel, javax.swing.GroupLayout.PREFERRED_SIZE, 355, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(30, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>      
    
    private ArrayList<WeightedVoter> getVotes() {
        ArrayList<WeightedVoter> result = new ArrayList<WeightedVoter>();
        DefaultTableModel votersModel = (DefaultTableModel) votersTable.getModel();
        for (Object o : votersModel.getDataVector()) {
            Vector v = (Vector)o;
            Object nameO = v.elementAt(0);
            Object weightO = v.elementAt(1);
            if (nameO == null) {
                JOptionPane.showMessageDialog(this, "Eintrag ohne Namen gefunden. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            String name = nameO.toString();
            if (name.equals("")) {
                JOptionPane.showMessageDialog(this, "Eintrag ohne Namen gefunden. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            if (weightO == null) {
                JOptionPane.showMessageDialog(this, "Eintrag für \"" + name + "\" ohne Gewicht. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            if (weightO.toString().equals("")) {
                JOptionPane.showMessageDialog(this, "Eintrag für \"" + name + "\" ohne Gewicht. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            WeightedVoter voter = null;
            if (ignoreWeightCheckBox.isSelected()) {
                voter = new WeightedVoter(name, 1);
            } else {
                voter = new WeightedVoter(name, Integer.parseInt(weightO.toString()));
            }
            result.add(voter);
        }
        return result;
    }

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                  
        this.dispatchEvent(new java.awt.event.WindowEvent(this, java.awt.event.WindowEvent.WINDOW_CLOSING));
    }                                            

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) { 
        String text = "<html>Copyright (C) 2014 Fabian Wenzelmann &lt;fabianwenzelmann@gmail.com&gt;<br><br>" +
            "License: stura_voting is free software: you can redistribute it and/or modify<br>" +
            "it under the terms of the GNU General Public License as published by the<br>" + 
            "Free Software Foundation, either version 3 of the License, or<br>" + 
            "(at your option) any later version.<br><br>" +
            "stura_voting is distributed in the hope that it will be useful, but<br>" + 
            "<b>WITHOUT ANY WARRANTY</b>; without even the implied warranty of<br>" + 
            "<b>MERCHANTABILITY</b> or <b>FITNESS FOR A PARTICULAR PURPOSE</b>.<br>" + 
            "See the GNU General Public License for more details.<br><br>" +
            "You should have received a copy of the GNU General Public License<br>" + 
            "along with stura_voting.<br><br>" +
            "If not, see &lt;http://www.gnu.org/licenses/&gt;.</html>";
        ImageIcon gplIcon = null;
        try {
            gplIcon = new ImageIcon(getClass().getResource(GPL_ICON_PATH));
        } catch(Exception e) { }
        JOptionPane.showMessageDialog(this, text, "About", JOptionPane.INFORMATION_MESSAGE, gplIcon);
    }                                             

    private void openWeightMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                
        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
            WeightParser parser = new WeightParser();
            try {
                BufferedReader reader = new BufferedReader(new FileReader(fileChooser.getSelectedFile()));
                ArrayList<WeightedVoter> voters = parser.parseWeights(reader);
                DefaultTableModel model = (DefaultTableModel) votersTable.getModel();
                model.setRowCount(0);
                for (WeightedVoter v : voters) {
                    model.addRow(new Object[]{v.getVoter(), "" + v.getWeight()});
                }
            } catch(java.io.FileNotFoundException e) {
                JOptionPane.showMessageDialog(this, "Angegebene Datei konnte nicht gefunden werden.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
            } catch (java.io.IOException e) {
                JOptionPane.showMessageDialog(this, "Fehler beim Lesen der Datei.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
            } catch (de.stura.WeightFormatException e) {
                String error = "Die Datei ist nicht korrekt formatiert.\n\n" +
                    e.getMessage();
                JOptionPane.showMessageDialog(this, error,
                    "Fehler", JOptionPane.ERROR_MESSAGE);
            }
        }
        
    }                                                  

    private void addVoterRowActionPerformed(java.awt.event.ActionEvent evt) {                                            
        DefaultTableModel model = (DefaultTableModel) votersTable.getModel();
        model.addRow(new Object[]{"", ""});
    }                                           

    private void createMedianButtonActionPerformed(java.awt.event.ActionEvent evt) {
        DefaultTableModel medianModel = (DefaultTableModel) medianTable.getModel();
        medianModel.setRowCount(0);
        ArrayList<WeightedVoter> voters = getVotes();
        for (WeightedVoter v : voters) {
            medianModel.addRow(new Object[]{v.getVoter(), v.getWeight(), null});
        }
    }                                                  

    private void evaluateMedianButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                     
        MedianEvaluator ev = new MedianEvaluator();
        DefaultTableModel medianModel = (DefaultTableModel) medianTable.getModel();
        ArrayList<MedianVote> votes = new ArrayList<MedianVote>(medianModel.getRowCount());
        int withoutVote = 0;
        int reallyVoted = 0;
        boolean absoluteMajority = medianAbsoluteMajorityCheckBox.isSelected();
        for (Object o : medianModel.getDataVector()) {
            Vector v = (Vector)o;
            Object nameO = v.elementAt(0);
            Object weightO = v.elementAt(1);
            Object voteO = v.elementAt(2);
            assert(nameO != null);
            assert(weightO != null);
            String name = nameO.toString();
            Integer weight = Integer.parseInt(weightO.toString());
            float vote = 0;
            if (voteO == null || voteO.toString().equals("")) {
                withoutVote++;
                if (!absoluteMajority) {
                    continue;
                }
            } else {
                vote = Float.parseFloat(voteO.toString());
                reallyVoted++;
            }
            votes.add(new MedianVote(name, weight, vote));
        }
        Float result = ev.evaluate(votes);
        String text = "Gültige Stimmen: " + reallyVoted +
            "\nOhne Stimme: " + withoutVote + "\n" +
            (absoluteMajority ? ("Abstimmung mit absoluter Mehrheit. Gezählte Stimmen: " + votes.size()) :
                "Abstimmung ohne absolute Mehrheit") +
            "\nGenehmigter Betrag: ";
        String val;
        if (result == null) {
            val = "Keiner (Fehler in der Berechnung)";
        } else {
            val = result.toString() + " €";
        }
        text += val;
        ImageIcon moneyIcon = null;
        try {
            moneyIcon = new ImageIcon(getClass().getResource(MONEY_ICON_PATH));
        } catch(Exception e) { }
        JOptionPane.showMessageDialog(this, text, "Auswertung Median-Verfahren",
            JOptionPane.INFORMATION_MESSAGE, moneyIcon);
    }
    
    private void saveWeightMenuItemActionPerformed(java.awt.event.ActionEvent evt) {   
        int returnVal = fileChooser.showSaveDialog(this);
        if (returnVal != javax.swing.JFileChooser.APPROVE_OPTION) {
            return;
        }
        DefaultTableModel model = (DefaultTableModel) votersTable.getModel();
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(fileChooser.getSelectedFile()));
            for (Object o : model.getDataVector()) {
                Vector v = (Vector)o;
                Object nameO = v.elementAt(0);
                if (nameO == null) {
                    continue;
                }
                String name = nameO.toString();
                if (name.equals("")) {
                    continue;
                }
                Object weightO = v.elementAt(1);
                if (weightO == null) {
                    continue;
                }
                if (weightO.toString().equals("")) {
                    continue;
                }
                int weight = Integer.parseInt(weightO.toString());
                String line = name + "\t" + weight;
                writer.write(line);
                writer.newLine();
            }
            writer.flush();
            writer.close();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Speichern der Datei fehlgeschlagen.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
        }
    }      
                                            
    private void createSchulzeButtonActionPerformed(java.awt.event.ActionEvent evt) {
        DefaultTableModel votersModel = (DefaultTableModel) votersTable.getModel();
        DefaultTableModel schulzeModel = (DefaultTableModel) schulzeTable.getModel();
        schulzeModel.setRowCount(0);
        for (Object o : votersModel.getDataVector()) {
            Vector v = (Vector)o;
            Object nameO = v.elementAt(0);
            Object weightO = v.elementAt(1);
            if (nameO == null) {
                JOptionPane.showMessageDialog(this, "Eintrag ohne Namen gefunden. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            String name = nameO.toString();
            if (name.equals("")) {
                JOptionPane.showMessageDialog(this, "Eintrag ohne Namen gefunden. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            if (weightO == null) {
                JOptionPane.showMessageDialog(this, "Eintrag für \"" + name + "\" ohne Gewicht. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            if (weightO.toString().equals("")) {
                JOptionPane.showMessageDialog(this, "Eintrag für \"" + name + "\" ohne Gewicht. Wird ignoriert.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                continue;
            }
            Integer weight = Integer.parseInt(weightO.toString());
            schulzeModel.addRow(new Object[]{name, weight, null});
        }
    }                                                   

    private void evaluateSchulzeButtonActionPerformed(java.awt.event.ActionEvent evt) {   
        // ask the user to input the names of the choices, separated by ',' 
        ImageIcon inputIcon = null;
        try {
            inputIcon = new ImageIcon(getClass().getResource(TEXT_ICON_PATH));
        } catch(Exception e) { }                                                  
        String s = (String)JOptionPane.showInputDialog(
                    this,
                    "Auswahl Abstimmungsgegenstände",
                    "Schulze-Methode",
                    JOptionPane.PLAIN_MESSAGE,
                    inputIcon,
                    null,
                    "");
        if (s != null) {
            s = s.trim();
        } else {
            return;
        }
        if (s.equals("")) {
            JOptionPane.showMessageDialog(this, "Eingabe muss eine Folge von Abstimmungsgegenständen sein,\ngetrennt durch Kommata.",
                    "Fehler", JOptionPane.ERROR_MESSAGE);
            return;
        }
        String[] names = s.split(",");
        StringBuilder infoText = new  StringBuilder("<html><h1>Nummerierung der Abstimmungsgegenstände</h1><ol start=\"0\">");
        for (String n : names) {
            infoText.append("<li>");
            infoText.append(n);
            infoText.append("</li>");
        }
        infoText.append("<li>Dagegen</li>");
        infoText.append("</ol></html>");
        final String infoString = infoText.toString();
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new InfoFrame(infoString, "Schulze Nummerierung").setVisible(true);
            }
        });
        int numVotes = names.length;
        SchulzeEvaluator ev = new SchulzeEvaluator(numVotes);
        DefaultTableModel schulzeModel = (DefaultTableModel) schulzeTable.getModel();
        int withoutVote = 0;
        int withVote = 0;
        for (Object o : schulzeModel.getDataVector()) {
            Vector v = (Vector)o;
            Object nameO = v.elementAt(0);
            Object weightO = v.elementAt(1);
            Object voteO = v.elementAt(2);
            assert(nameO != null);
            assert(weightO != null);
            String name = nameO.toString();
            Integer weight = Integer.parseInt(weightO.toString());
            if (voteO == null) {
                withoutVote++;
                continue;
            }
            if (voteO.toString().equals("")) {
                withoutVote++;
                continue;
            }
            try {
                ArrayList<SchulzeVote> vote = ev.fromString(voteO.toString());
                for (int i = 0; i < weight; ++i) {
                    ev.addVote(vote);
                }
                withVote++;
            } catch (SchulzeParseException e) {
                JOptionPane.showMessageDialog(this, "Ungültige Eingabe für '" + name + "'.\nFehler:\n\n" + e.getMessage(),
                    "Fehler", JOptionPane.ERROR_MESSAGE);
                    withoutVote++;
                continue;
            }
        }
        ArrayList<ArrayList<Integer>> voteResult = ev.evaluate();
        // Display result...
        StringBuilder resultText = new StringBuilder("<html><h1>Schulze-Methode: Ergenisse</h1>");
        resultText.append("Gültige Stimmen: ");
        resultText.append(withVote);
        resultText.append("<br/>");
        resultText.append("Ohne Stimme: ");
        resultText.append(withoutVote);
        resultText.append("<br/>Die Reihung der Ergebnisse ist wie folgt<br/>");
        resultText.append("(Gruppe mit den besten Ergebnissen und darunter alle Abstimmungsgegenstände der Gruppe):");
        resultText.append("<ol>");
        for (ArrayList<Integer> group : voteResult) {
            resultText.append("<li>Gruppe</li><ol>");
            for (int val : group) {
                resultText.append("<li>");
                if (val >= names.length) {
                    resultText.append("Dagegen");
                } else {
                    resultText.append(names[val]);
                }
                resultText.append("</li>");
            }
            resultText.append("</ol>");
        }
        resultText.append("</ol>");
        resultText.append("<h2>Zwischenergebnisse: Matrix d</h2>");
        resultText.append(ev.getLastDHTML());
        resultText.append("<h2>Zwischenergebnisse: Matrix p</h2>");
        resultText.append(ev.getLastPHTML());
        resultText.append("</html>");
        final String resultString = resultText.toString();
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new InfoFrame(resultString, "Schulze Ergebnisse").setVisible(true);
            }
        });
    }
    
    private void evaluateMultipleSchulzeButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                              
        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
            // used to transform the array lists to a hashmap
            WeightParser wp = new WeightParser();
            SchulzeFileParser parser = new SchulzeFileParser();
            ArrayList<SchulzeEvaluator> votings = null;
            ArrayList<WeightedVoter> weightedVotes = getVotes();
            try {
                BufferedReader reader = new BufferedReader(new FileReader(fileChooser.getSelectedFile()));
                HashMap<String, WeightedVoter> weights = wp.mapFromList(weightedVotes);
                FrameSchulzeHandler handler = new FrameSchulzeHandler();
                votings = parser.parse(reader, weights, handler);
                System.out.println(votings.size());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //</editor-fold>

    // Variables declaration - do not modify                     
    private javax.swing.JMenu Help;
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JButton addVoterRow;
    private javax.swing.JButton createMedianButton;
    private javax.swing.JButton createSchulzeButton;
    private javax.swing.JButton evaluateMedianButton;
    private javax.swing.JButton evaluateMultipleSchulzeButton;
    private javax.swing.JButton evaluateSchulzeButton;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JCheckBox ignoreWeightCheckBox;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JCheckBox medianAbsoluteMajorityCheckBox;
    private javax.swing.JPanel medianPanel;
    private javax.swing.JTable medianTable;
    private javax.swing.JMenuItem openWeightMenuItem;
    private javax.swing.JMenuItem saveWeightMenuItem;
    private javax.swing.JCheckBox schulzeAbsoluteMajorityCheckBox;
    private javax.swing.JTabbedPane schulzePannel;
    private javax.swing.JTable schulzeTable;
    private javax.swing.JCheckBox schulzeTwoThirdsMajorityCheckBox;
    private javax.swing.JPanel votersPanel;
    private javax.swing.JTable votersTable;
    // End of variables declaration
    
    // self designed variables
    private javax.swing.JFileChooser fileChooser;
    public static final String GPL_ICON_PATH = "/icons/gplv3.png";
    public static final String MONEY_ICON_PATH = "/icons/money.png";
    public static final String TEXT_ICON_PATH = "/icons/text-x-generic.png";
}
